package cheme.ProcessModel.ProcessUnits.Streams.Tags;

import java.io.IOException;
import java.io.Serializable;

import cheme.ProcessModel.AbstractParent;
import cheme.ProcessModel.ChemePropertyChangeEvent;
import cheme.ProcessModel.IChild;
import cheme.ProcessModel.IModelElement;
import cheme.ProcessModel.IPropertyAware;
import cheme.ProcessModel.ModelEnv;
import cheme.ProcessModel.ProcessModelConstants;
import cheme.ProcessModel.Errors.ChemeInvalidTypeError;
import cheme.ProcessModel.Visitors.IModelVisitor;

public class TagComponentList extends AbstractParent<IGeneralTagComponent> implements Serializable
{
	/*
	 * Serialization version identifier. (Set to default for now)
	 */
	
	private static final long serialVersionUID = 1L;
	
	ITagComponentInitPolicy initPolicy = null;

//	private QuantityManager quantityManager = null;
	
	/**
	 * 
	 * @param parent
	 * @param initBasis the overall component which list components will emulate for initialization purposes
	 */
	public TagComponentList(IModelElement parent)
	{
		super(parent);
		
//		quantityManager = new QuantityManager(initBasis);		
	}

	public void initialize()
	{ 
		add((TagComponent)ModelEnv.getInstanceFor(this).createModelElement(ProcessModelConstants.TAG_COMPONENT, this));
	}
	
	public ITagComponentInitPolicy getInitPolicy()
	{
		return initPolicy;
	}

	// private void writeObject(java.io.ObjectOutputStream out) throws
	// IOException
	// {
	// }
	 
	 private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
	 {
		/*
		 * Make sure the interpreter can listen to my changes. Specifically,
		 * when a tag component is added to this list, the addition needs to
		 * trigger an initial interpretation of that component. Likewise,
		 * removal needs to be processed.
		 */
		 
		 ModelEnv.getInstanceFor(this).hookModelElement(this);
		 
		 /*
		  * Make sure I can listen to my children created form a past session.
		  */
		 
		 for(IChild child : getChildren())
		 {
			 child.addPropertyChangeListener(this);
		 }
	 }
	 
	public void add(IGeneralTagComponent child)
	{
		if(!(child instanceof IGeneralTagComponent))
		{
			throw new ChemeInvalidTypeError();
		}
				
		super.add(child);
		
		/*
		 * Applying the init policy after adding (and also hooking the child to
		 * the interpreter) allows the interpreter to tag any error that occur
		 * asa result of propogating errors from the init policy to this child.
		 */
		
		child.initialize(getNamingPolicy());
	}

	public ITagComponentInitPolicy getNamingPolicy()
	{
		return initPolicy;
	}

	public void setNamingPolicy(ITagComponentInitPolicy namingPolicy)
	{
		this.initPolicy = namingPolicy;
	}
	
	/*
	 * Note that this is intercepting the fireing of events due to adding or
	 * removing equation tokens, this method does not respond to events from the
	 * child tokens.
	 */
	
	@Override
	public void firePropertyChange(ChemePropertyChangeEvent evt)
	{
		super.firePropertyChange(evt);
		
		if(evt.getPropertyName().equals(IPropertyAware.P_CHILD) || //change in children set membership--common, this one.
			evt.getPropertyName().equals(IPropertyAware.P_CHILDREN))//ditto
		{
			super.firePropertyChange(
					new ChemePropertyChangeEvent(this, P_INTERPRETABLE, evt.getOldValue(), evt.getNewValue(), evt));
		}
	}

//	public QuantityManager getQuantityManager()
//	{
//		return quantityManager;
//	}
//
//	public void setQuantityManager(QuantityManager quantityManager)
//	{
//		this.quantityManager = quantityManager;
//	}
	
	/*
	 *--------------------------------------------------------------------------
	 * Seperates individual children text representations.
	 */
	
	@Override
	protected String getToStringSeparator()
	{
		return "\n------------------------------------\n";
	}
	
	public Object accept(IModelVisitor ruleChecker)
	{
		return ruleChecker.visit(this);
	}
}
